/*
 * NIST Message Maker
 * EventModel.java Oct 29, 2009
 *
 * This code was produced by the National Institute of Standards and
 * Technology (NIST). See the "nist.disclaimer" file given in the distribution
 * for information on the use and redistribution of this software.
 */
package gov.nist.healthcare.testframework.event;

import gov.nist.healthcare.core.message.Message;
import gov.nist.healthcare.core.message.Name;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;

/**
 * This class stores all the events that occurs in the test framework.
 * 
 * @author Sydney Henrard (NIST)
 */
public class EventModel extends Observable {

    public enum EventType {
        INCOMING_MESSAGE_TEST_AGENT, INCOMING_MESSAGE_TEST_FRAMEWORK, OUTGOING_MESSAGE_TEST_AGENT, OUTGOING_MESSAGE_TEST_FRAMEWORK, ERROR_MESSAGE, WARNING_MESSAGE, INFO_MESSAGE, ERROR_MESSAGE_WEB_APP, WARNING_MESSAGE_WEB_APP, INFO_MESSAGE_WEB_APP, COMMUNICATION_MESSAGE, VALIDATION_RESULT_TEST_AGENT
    };

    // public enum Layer {
    // TEST_FRAMEWORK, TEST_AGENT
    // };

    /**
     * Generic event.
     * 
     * @param params
     */
    public void genericEvent(Map<String, Object> params) {
        setChanged();
        notifyObservers(params);
    }

    /**
     * An incoming message is received by the test framework. The event requires
     * the name of the sender and receiver, the message.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param message
     *        the message involved in the exchange
     */
    public void incomingMessageTestFramework(Name sender, Name receiver,
            Message message) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", EventType.INCOMING_MESSAGE_TEST_FRAMEWORK);
        params.put("sender", sender);
        params.put("receiver", receiver);
        params.put("message", message);
        setChanged();
        notifyObservers(params);
    }

    /**
     * An incoming message is received by the test framework. The event requires
     * the message as a String.
     * 
     * @param message
     *        the message as a String
     */
    public void incomingMessageTestFramework(String message) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", EventType.INCOMING_MESSAGE_TEST_FRAMEWORK);
        params.put("message", message);
        setChanged();
        notifyObservers(params);
    }

    /**
     * An incoming message is received by the test agent. The event requires the
     * name of the sender and receiver, the message.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param message
     *        the message involved in the exchange
     */
    public void incomingMessageTestAgent(Name sender, Name receiver,
            Message message) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", EventType.INCOMING_MESSAGE_TEST_AGENT);
        params.put("sender", sender);
        params.put("receiver", receiver);
        params.put("message", message);
        setChanged();
        notifyObservers(params);
    }

    /**
     * An outgoing message is sent by the test framework. The event requires the
     * name of the sender and receiver, the message.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param message
     *        the message involved in the exchange
     */
    public void outgoingMessageTestFramework(Name sender, Name receiver,
            Message message) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", EventType.OUTGOING_MESSAGE_TEST_FRAMEWORK);
        params.put("sender", sender);
        params.put("receiver", receiver);
        params.put("message", message);
        setChanged();
        notifyObservers(params);
    }

    /**
     * An outgoing message is sent by the test framework. The event requires the
     * name of the sender and receiver, the message.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param message
     *        the message involved in the exchange
     */
    public void outgoingMessageTestAgent(Name sender, Name receiver,
            Message message) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", EventType.OUTGOING_MESSAGE_TEST_AGENT);
        params.put("sender", sender);
        params.put("receiver", receiver);
        params.put("message", message);
        setChanged();
        notifyObservers(params);
    }

    /**
     * Log a message.
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param description
     *        the description
     * @param message
     *        the message responsible of the error
     * @param eventType
     *        the eventType
     */
    private void log(String sourceClass, String sourceMethod,
            String description, Message message, EventType eventType) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", eventType);
        params.put("sourceClass", sourceClass);
        params.put("sourceMethod", sourceMethod);
        params.put("description", description);
        params.put("message", message);
        setChanged();
        notifyObservers(params);
    }

    /**
     * Log an ERROR message. The event requires the location (class and method
     * name), the description.
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param description
     *        the description
     */
    public void error(String sourceClass, String sourceMethod,
            String description) {
        log(sourceClass, sourceMethod, description, null,
                EventType.ERROR_MESSAGE);
    }

    /**
     * Log an ERROR message. The event requires the location (class and method
     * name), the description and the message responsible of the error.
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param description
     *        the description
     * @param message
     *        the message responsible of the error
     */
    public void error(String sourceClass, String sourceMethod,
            String description, Message message) {
        log(sourceClass, sourceMethod, description, message,
                EventType.ERROR_MESSAGE);
    }

    /**
     * Log a WARNING message. The event requires the location (class and method
     * name), the description.
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param description
     *        the description
     */
    public void warning(String sourceClass, String sourceMethod,
            String description) {
        log(sourceClass, sourceMethod, description, null,
                EventType.WARNING_MESSAGE);
    }

    /**
     * Log an INFO message. The event requires the location (class and method
     * name), the description.
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param description
     *        the description
     */
    public void info(String sourceClass, String sourceMethod, String description) {
        log(sourceClass, sourceMethod, description, null,
                EventType.INFO_MESSAGE);
    }

    /**
     * Log a throwable. The event requires the location (class and method name).
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param thrown
     *        the Throwable that is being thrown
     */
    public void throwable(String sourceClass, String sourceMethod,
            Throwable thrown) {
        log(sourceClass, sourceMethod, String.format("%s: %s",
                thrown.getClass().getCanonicalName(), thrown.getMessage()),
                null, EventType.ERROR_MESSAGE);
    }

    /**
     * Log a COMMUNICATION message. The event requires the location (class and
     * method name), the description.
     * 
     * @param sourceClass
     *        the classname
     * @param sourceMethod
     *        the method name
     * @param description
     *        the description
     */
    public void communication(String sourceClass, String sourceMethod,
            String description) {
        log(sourceClass, sourceMethod, description, null,
                EventType.COMMUNICATION_MESSAGE);
    }

    /**
     * Log a message.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param description
     *        the description
     * @param eventType
     *        the eventType
     */
    private void log(Name sender, Name receiver, String description,
            EventType eventType) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("eventType", eventType);
        params.put("sender", sender);
        params.put("receiver", receiver);
        params.put("description", description);
        setChanged();
        notifyObservers(params);
    }

    /**
     * Log an ERROR message for the web application. The event requires the name
     * of the sender and receiver and the description.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param description
     *        the description
     */
    public void errorWebApp(Name sender, Name receiver, String description) {
        log(sender, receiver, description, EventType.ERROR_MESSAGE_WEB_APP);
    }

    /**
     * Log a WARNING message for the web application. The event requires the
     * name of the sender and receiver and the description.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param description
     *        the description
     */
    public void warningWebApp(Name sender, Name receiver, String description) {
        log(sender, receiver, description, EventType.WARNING_MESSAGE_WEB_APP);
    }

    /**
     * Log an INFO message for the web application. The event requires the name
     * of the sender and receiver and the description.
     * 
     * @param sender
     *        the sender
     * @param receiver
     *        the receiver
     * @param description
     *        the description
     */
    public void infoWebApp(Name sender, Name receiver, String description) {
        log(sender, receiver, description, EventType.INFO_MESSAGE_WEB_APP);
    }

}
